package com.kingsoft.dc.khaos.util

import org.apache.log4j.{Level, LogManager, PropertyConfigurator}
import org.slf4j.impl.StaticLoggerBinder
import org.slf4j.{Logger, LoggerFactory}

/**
  * Created by chengguangqing on 2019/6/12.
  */
trait Logging {

  @transient private var log_ : Logger = null


  protected def logName ={
    this.getClass.getName.stripSuffix("$")
  }

  protected def log: Logger = {
    if(log_ == null){
      initializeLogIfNecessary(false)
      log_ = LoggerFactory.getLogger(logName)
    }
    log_
  }

  protected def logInfo(msg: => String): Unit ={
    if(log.isInfoEnabled) log.info(msg)
  }

  protected def logDebug(msg: => String):Unit = {
    if(log.isDebugEnabled) log.debug(msg)
  }

  protected def logTrace(msg: => String): Unit ={
    if (log.isTraceEnabled) log.trace(msg)
  }

  protected def logWarning(msg: => String): Unit ={
    if (log.isWarnEnabled) log.warn(msg)
  }

  protected def logError(msg: => String) {
    if (log.isErrorEnabled) log.error(msg)
  }

  // Log methods that take Throwables (Exceptions/Errors) too
  protected def logInfo(msg: => String, throwable: Throwable) {
    if (log.isInfoEnabled) log.info(msg, throwable)
  }

  protected def logDebug(msg: => String, throwable: Throwable) {
    if (log.isDebugEnabled) log.debug(msg, throwable)
  }

  protected def logTrace(msg: => String, throwable: Throwable) {
    if (log.isTraceEnabled) log.trace(msg, throwable)
  }

  protected def logWarning(msg: => String, throwable: Throwable) {
    if (log.isWarnEnabled) log.warn(msg, throwable)
  }

  protected def logError(msg: => String, throwable: Throwable) {
    if (log.isErrorEnabled) log.error(msg, throwable)
  }


  protected def isTraceEnabled(): Boolean = {
    log.isTraceEnabled
  }

  protected def initializeLogIfNecessary(isInterpreter:Boolean): Unit ={
    if(!Logging.initialized){
      Logging.initLock.synchronized{
        if(!Logging.initialized){
          initializeLogging(isInterpreter)
        }
      }
    }
  }

  private def initializeLogging(isInterpreter: Boolean): Unit ={
    val binderClass = StaticLoggerBinder.getSingleton.getLoggerFactoryClassStr
    val usingLog4j12= "org.slf4j.impl.Log4jLoggerFactory".equals(binderClass)
    if(usingLog4j12){
      val log4j12Initialized = LogManager.getRootLogger.getAllAppenders.hasMoreElements
      if(log4j12Initialized){
        val defaultLogProps="log4j-spark.properties"
        Option(getClass.getClassLoader.getResource(defaultLogProps)) match{
          case Some(url) =>
            PropertyConfigurator.configure(url)
            System.err.println(s"Using Khaos's default log4j profile: $defaultLogProps")
          case None =>
            System.out.println(s"Khaos was unable to load $defaultLogProps")
        }
      }
      //待开放功能
      if(false){
        val rootLogger = LogManager.getRootLogger()
        val localLogger = LogManager.getLogger(logName)
        val localLevel = Option(localLogger.getLevel).getOrElse(Level.WARN)
        if(localLevel != rootLogger.getEffectiveLevel){
          System.err.print("Setting default log level to \"%s\".\n", localLevel)
        }
        rootLogger.setLevel(localLevel)
      }
    }
    Logging.initialized = true
    log
  }
}

private object Logging{
  private var initialized = false
  val initLock = new Object()
  try{
    val bridgeClass = Class.forName("org.slf4j.bridge.SLF4JBridgeHandler",true,Thread.currentThread().getContextClassLoader)
    bridgeClass.getMethod("removeHandlersForRootLogger").invoke(null)
    val installed = bridgeClass.getMethod("isInstalled").invoke(null).asInstanceOf[Boolean]
    if(!installed){
      bridgeClass.getMethod("install").invoke(null)
    }
  } catch {
    case e:ClassNotFoundException =>
  }
}

